package com.atguigu04.threadsafemore.singleton;

//懒汉式单例模式--不安全
class Singleton {


    private Singleton() {
    }

    private volatile static Singleton instance = null;

    //方式1 存在线程安全问题
//    public static Singleton getInstance() {
//
//        try {
//            Thread.sleep(100);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//        if (instance == null) {
//            instance = new Singleton();
//        }
//        return instance;
//    }

    //方式1：使用同步方法
//    public synchronized static Singleton getInstance() {
//
//        if (instance == null) {
//            try {
//                Thread.sleep(100);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            instance = new Singleton();
//        }
//        return instance;
//    }
    //方式2：使用同步代码块
//    public static Singleton getInstance() {
//
//        synchronized (Singleton.class){
//
//            if (instance == null) {
//                try {
//                    Thread.sleep(100);
//                } catch (InterruptedException e) {
//                    e.printStackTrace();
//                }
//                instance = new Singleton();
//            }
//        }
//        return instance;
//    }

    //方式3：相较于方式1和方式2来讲，效率更高。为了避免出现指令重排，需要将instance声明为volatile
    public static Singleton getInstance() {

        if(instance == null) {

            synchronized (Singleton.class){

                if (instance == null) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    instance = new Singleton();
                }

            }
        }
        return instance;
    }

}

public class SingletonTest {


    static Singleton instance1 = null;
    static Singleton instance2 = null;

    public static void main(String[] args) throws InterruptedException {

        Thread t1 = new Thread() {
            @Override
            public void run() {
                instance1 = Singleton.getInstance();
            }
        };

        Thread t2 = new Thread() {
            @Override
            public void run() {
                instance2 = Singleton.getInstance();
            }
        };

        t1.start();
        t2.start();


        t1.join();
        t2.join();


        System.out.println(instance1);
        System.out.println(instance2);

        System.out.println(instance1 == instance2);

    }
}
